<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <script src="//code.jquery.com/jquery-2.0.0.js"></script>
    <style>
    #map {
      background-color: #fff;
      border: 1px solid #ccc;
    }
    .background {
      fill: none;
      pointer-events: all;
    }
    #countries, #states {
      fill: #cde;
      stroke: #fff;
      stroke-linejoin: round;
      stroke-linecap: round;
    }
    #countries .active, #states .active {
      fill: #89a;
    }
    #cities {
      stroke-width: 0;
    }
    .city {
      fill: #345;
      stroke: #fff;
    }
    pre.prettyprint {
      border: 1px solid #ccc;
      margin-bottom: 0;
      padding: 9.5px;
    }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="//d3js.org/topojson.v1.min.js"></script>
    <script>
    var m_width = $("#map").width(),
        width = 938,
        height = 500,
        country,
        state;

    var projection = d3.geo.mercator()
        .scale(300)
        .translate([width , height+50 ]);

    var path = d3.geo.path()
        .projection(projection);

    var svg = d3.select("#map").append("svg")
        .attr("preserveAspectRatio", "xMidYMid")
        .attr("viewBox", "0 0 " + width + " " + height)
        .attr("width", m_width)
        .attr("height", m_width * height / width);

    svg.append("rect")
        .attr("class", "background")
        .attr("width", width)
        .attr("height", height)
        .on("click", state_clicked);

    var g = svg.append("g");


    function zoom(xyz) {
      g.transition()
        .duration(750)
        .attr("transform", "translate(" + projection.translate() + ")scale(" + xyz[2] + ")translate(-" + xyz[0] + ",-" + xyz[1] + ")")
        .selectAll(["#states", "#cities"])
        .style("stroke-width", 1.0 / xyz[2] + "px")
        .selectAll(".city")
        .attr("d", path.pointRadius(1));
    }

    function get_xyz(d) {
      var bounds = path.bounds(d);
      var w_scale = (bounds[1][0] - bounds[0][0]) / width;
      var h_scale = (bounds[1][1] - bounds[0][1]) / height;
      var z = 5.0 / Math.max(w_scale, h_scale);
      var x = (bounds[1][0] + bounds[0][0])/2 ;
      var y = (bounds[1][1] + bounds[0][1]) /2 + (height / z / 6);
      return [x, y, z];
    }

   
 
    d3.json("states_usa.topo.json", function(error, us) {
       g.append("g")
       .attr("id", "states")
       .selectAll("path")
       .data(topojson.feature(us, us.objects.states).features)
       .enter()
       .append("path")
       .attr("id", function(d) { return d.id; })
       .attr("class", "active")
       .attr("d", path)
       .on("click", state_clicked);
    
    d3.json("modified_us_cities.topo.json", function(error, us) {
        g.append("g")
       .attr("id", "cities")
       .selectAll("path")
       .data(topojson.feature(us, us.objects.cities).features)//.filter(function(d) { return state_name == d.properties.state; }))
       .enter()
       .append("path")
       .attr("id", function(d) { return d.properties.name; })
       .attr("class", "city")
       .attr("d", path.pointRadius(1));// / xyz[2]));

         
    }); 

          
    });      
 

    function state_clicked(d) {
      if (d && state !== d) {
        var xyz = get_xyz(d);
        state = d;
        zoom(xyz);         
        }             
       else {
        state = null;
        var xyz = [width, height + 50, 1];
        zoom(xyz);       
      }
    }

    $(window).resize(function() {
      var w = $("#map").width();
      svg.attr("width", w);
      svg.attr("height", w * height / width);
    });
    </script>
  </body>
</html>
